package net.i_tatami.slab.mazesearch.maze;



import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;

public class Maze {
	public final static int WALL = 0;
	public final static int ROAD = 1;
	public final static int NORTH = 0;
	public final static int EAST = 1;
	public final static int WEST = 2;
	public final static int SOUTH = 3;
	private int width;
	private int height;
	private int[][] circumstance;
	private Point start, goal;
	
	public Maze(){
		this(11, 11, new Point(1, 1),new Point(9, 9));	
	}

	public Maze(int width, int height, Point start, Point goal){
		this.start = start;
		this.goal = goal;
		this.width = width;
		this.height = height;
		this.circumstance = new int[height][width];
		for(int i = 0 ; i<this.height ; i++){
			for(int j = 0 ; j<this.width ; j++){
				this.circumstance[i][j] = WALL;
			}
		}
		setCircumstance(start.x, start.y, ROAD);
		generateRoute(start.x, start.y, 0, 1);	
	}
	
	private void generateRoute(int x, int y, int dx, int dy){
		int nextX = x + dx*2;
		int nextY = y + dy*2;
		
		if(nextX < 0 || nextX >= width || nextY < 0 || nextY >= height){
			return;
		} 
		if(getCircumstance(nextX, nextY) == ROAD){
			return;
		}
		setCircumstance(nextX, nextY, ROAD);
		setCircumstance(x+dx, y+dy, ROAD);
		if(nextX == goal.x && nextY == goal.y){
			return;
		}
		ArrayList<Integer> candidate = new ArrayList<Integer>();
		for(int i=0 ; i<4 ; i++){
			candidate.add(i);
		}
		while(!candidate.isEmpty()){
			int index = (new Random().nextInt(4)%candidate.size());
			int nextDirection = candidate.get(index);
			candidate.remove(index);
			switch(nextDirection){
			case 0:
				generateRoute(nextX, nextY, 0, -1);	
				break;
			case 1:
				generateRoute(nextX, nextY, 0, 1);	
				break;
			case 2:
				generateRoute(nextX, nextY, -1, 0);	
				break;
			case 3:
				generateRoute(nextX, nextY, 1, 0);	
				break;
			}
		}
	}
	
	public int getCircumstance(int x, int y) {
		return circumstance[y][x];
	}

	public void setCircumstance(int x, int y, int circumstance) {
		this.circumstance[y][x] = circumstance;
	}

	public int getHeight() {
		return height;
	}

	public int getWidth() {
		return width;
	}

	public Point getGoal() {
		return goal;
	}
	
	public void setGoal(Point goal){
		this.goal = goal;
	}

	public Point getStart() {
		return start;
	}
}
